package com.baomidou.springwind.controller;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.framework.common.util.DateUtil;
import com.baomidou.kisso.annotation.Permission;
import com.baomidou.springwind.entity.Resource;
import com.baomidou.springwind.enums.ResourceEnum;
import com.baomidou.springwind.service.*;
import com.glc.lpp.simulation.SimuFactory;
import com.glc.lpp.simulation.SimuMain;
import com.glc.lpp.simulation.res.Equipment;
import com.glc.lpp.simulation.workstation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.text.DecimalFormat;
import java.util.*;

/**
 * <p>
 * 仓储模拟相关操作
 * </p>
 *
 * @Author demo
 * @Date 2017-5-28
 */
@Controller
@RequestMapping("/simulation")
public class SimulationController extends BaseController {

    @Autowired
    private ResourceService resourceService;

    @Autowired
    private ReceiveGoodsService receiveGoodsService;

    @Autowired
    private DeliveryGoodsService deliveryGoodsService;

    @Autowired
    private ProjectService projectService;
    private DecimalFormat df = new DecimalFormat("##.##");

    @Permission("1001")
    @RequestMapping("/view/{batchId}/{type}")
    public String view(@PathVariable String type, Model model) {
        Map<String, Object> params = new HashMap<String, Object>();
        Long batchId=Long.valueOf(getProjectId());
        params.put("batchId",batchId );
        final long start = System.currentTimeMillis();
        if (session.getAttribute("simulation:" + batchId) == null) {
            SimuMain main = buildSimulation(batchId);
            if(main==null){
                return pjaxPath("/lpp/simu/main" + type,model);
            }
            main.simulate();
            session.setAttribute("simulation:" + batchId, main.getSnapshotMap());
        }
        model.addAttribute("prjList", projectService.getUserAllProjects());
        model.addAttribute("batchId", batchId);
        return pjaxPath("/lpp/simu/main" + type, model);
    }

    /**
     * 构建仓储仿真服务台信息
     */
    private SimuMain buildSimulation(Long batchId) {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("batch_id", batchId);
        List<Resource> resourceList = resourceService.selectByMap(params);
        if(resourceList.size()==0){
            return null;
        }
        Map<Integer, Resource> resourceMap = new HashMap(resourceList.size());
        for (Resource res : resourceList) {
            resourceMap.put(res.getResType(), res);
        }
        Equipment equ1 = SimuFactory.buildEquipment(resourceMap, ResourceEnum.EQUIPMENT_SALVER);
        Equipment electricTrunck = SimuFactory.buildEquipment(resourceMap, ResourceEnum.EQUIPMENT_ELECTRIC_TRUCK);
        Equipment pickupTrunck = SimuFactory.buildEquipment(resourceMap, ResourceEnum.EQUIPMENT_PICKUP_TRUCK);
        List<Map<String, Object>> goodsInList = receiveGoodsService.getReceiveGoodsList(batchId);
        List<Map<String, Object>> goodsOutList = deliveryGoodsService.getDeliveryGoodsList(batchId);
        if(goodsInList.size()==0){
            return null;
        }
        Date begin1 = (Date) goodsInList.get(0).get("time");
        Date begin2 = (Date) goodsOutList.get(0).get("time");
        Date minTime = begin1.before(begin2) ? begin1 : begin2;
        SimuMain main = new SimuMain(minTime);
        Map<Integer, Integer> goodsInMap = buildGoodsMap(goodsInList, minTime);
        Map<Integer, Integer> goodsOutMap = buildGoodsMap(goodsOutList, minTime);

        WorkStation store = SimuFactory.buildWorkStation(SimuFactory.buildOperator(resourceMap, ResourceEnum.OPERATOR_STORE), electricTrunck, SimuFactory.buildWorkSpace(resourceMap, ResourceEnum.WORKSPACE_STORE), null);
        WorkStation inspect = SimuFactory.buildWorkStation(SimuFactory.buildOperator(resourceMap, ResourceEnum.OPERATOR_INSPECT), SimuFactory.buildWorkSpace(resourceMap, ResourceEnum.WORKSPACE_INSPECT), store);
        WorkStation unload = SimuFactory.buildWorkStation(SimuFactory.buildOperator(resourceMap, ResourceEnum.OPERATOR_UNLOADER), electricTrunck, SimuFactory.buildWorkSpace(resourceMap, ResourceEnum.WORKSPACE_UNLOAD), inspect);// new UnloadStation(upload_oper, equ2, upload_space);
        unload.setGoodsMap(goodsInMap);

        WorkStation out = SimuFactory.buildWorkStation(SimuFactory.buildOperator(resourceMap, ResourceEnum.OPERATOR_OUT), electricTrunck, SimuFactory.buildWorkSpace(resourceMap, ResourceEnum.WORKSPACE_OUT), null);
        WorkStation recheck = SimuFactory.buildWorkStation(SimuFactory.buildOperator(resourceMap, ResourceEnum.OPERATOR_RECHECK), SimuFactory.buildWorkSpace(resourceMap, ResourceEnum.WORKSPACE_RECHECK), out);
        WorkStation pack = SimuFactory.buildWorkStation(SimuFactory.buildOperator(resourceMap, ResourceEnum.OPERATOR_PACKAGE), SimuFactory.buildWorkSpace(resourceMap, ResourceEnum.WORKSPACE_PACKAGE), recheck);
        WorkStation pickup = SimuFactory.buildWorkStation(SimuFactory.buildOperator(resourceMap, ResourceEnum.OPERATOR_PICKUP), pickupTrunck, SimuFactory.buildWorkSpace(resourceMap, ResourceEnum.WORKSPACE_PICKUP), pack);
        pickup.setGoodsMap(goodsOutMap);

        main.addWorkStation(unload);
        main.addWorkStation(inspect);
        main.addWorkStation(store);
        main.addWorkStation(pickup);
        main.addWorkStation(pack);
        main.addWorkStation(recheck);
        main.addWorkStation(out);
        return main;
    }

    private Map<Integer, Integer> buildGoodsMap(List<Map<String, Object>> goodsList, Date minTime) {
        Map<Integer, Integer> goodsMap = new HashMap<Integer, Integer>(goodsList.size());
        int count = 0;
        for (Map<String, Object> map : goodsList) {
            if (count++ > 10) break;
            Date time = (Date) map.get("time");
            Integer key = (int) DateUtil.dateDiff(minTime, time, 1000) + 1;
            if (goodsMap.containsKey(key)) {
                goodsMap.put(key, goodsMap.get(key) + (Integer) map.get("amount"));
            } else {
                goodsMap.put(key, (Integer) map.get("amount"));
            }
        }
        return goodsMap;
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/queue")
    public String getQueue( int index, Model model) {
        Long batchId=Long.valueOf(getProjectId());
        Map<String, List<Number>> snapshotMap = (Map<String, List<Number>>) session.getAttribute("simulation:" + batchId);
        JSONObject result = new JSONObject();
        JSONArray date = new JSONArray();
        JSONArray data = new JSONArray();
        int count = 0;
        for (Map.Entry<String, List<Number>> entry : snapshotMap.entrySet()) {
            if (count++ > 1000) continue;
            date.add(entry.getKey());
            data.add(entry.getValue().get(index));
        }
        result.put("date", date);
        result.put("data", data);
        return callbackSuccess(result);
    }

    @ResponseBody
    @Permission("1001")
    @RequestMapping("/resource")
    public String getResource( int index, Model model) {
        Long batchId=Long.valueOf(getProjectId());
        Map<String, List<Number>> snapshotMap = (Map<String, List<Number>>) session.getAttribute("simulation:" + batchId);
        JSONObject result = new JSONObject();
        JSONArray date = new JSONArray();
        JSONArray line = new JSONArray();
        int count = 0;
        for (Map.Entry<String, List<Number>> entry : snapshotMap.entrySet()) {
            if (count++ > 1000) continue;
            date.add(entry.getKey());
            line.add(df.format(entry.getValue().get(index)));
        }
        result.put("date", date);
        result.put("line", line);
        result.put("pie", getBusyRatio(snapshotMap, index));
        result.put("x1", getX1());
        return callbackSuccess(result);
    }
    public JSONArray getX1(){
        JSONArray ratio = new JSONArray();
        ratio.add("80%以上");
        ratio.add("60%-80%");
        ratio.add("40%-60%");
        ratio.add("20%-40%");
        ratio.add("20%以下");
        return ratio;
    }
    private JSONArray getBusyRatio(Map<String, List<Number>> snapshotMap, int index) {
        double num;
        JSONArray ratio = new JSONArray();
        int gt80 = 0;
        int bt6080 = 0;
        int bt4060 = 0;
        int bt2040 = 0;
        int lt20 = 0;
        for (Map.Entry<String, List<Number>> entry : snapshotMap.entrySet()) {
            num = entry.getValue().get(index).doubleValue();
            if (num >= 80) {
                gt80++;
            } else if (num >= 60 && num < 80) {
                bt6080++;
            } else if (num >= 40 && num < 60) {
                bt4060++;
            } else if (num >= 20 && num < 40) {
                bt2040++;
            } else {
                lt20++;
            }
        }
        ratio.add(JSONObject.parse("{value: " + gt80 + ", name: '80%以上'}"));
        ratio.add(JSONObject.parse("{value: " + bt6080 + ", name: '60%-80%'}"));
        ratio.add(JSONObject.parse("{value: " + bt4060 + ", name: '40%-60%'}"));
        ratio.add(JSONObject.parse("{value: " + bt2040 + ", name: '20%-40%'}"));
        ratio.add(JSONObject.parse("{value: " + lt20 + ", name: '20%以下'}"));
        return ratio;
    }
}
